
package edu.moravian.managers;

import edu.moravian.collisionphysics.CollisionEngine;
import edu.moravian.entity.Enemy;
import edu.moravian.entity.Ordinance;
import edu.moravian.world.WorldDescriptor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 *
 * @author ronaghan
 */
public class OrdinanceManager
{
    private static final double ELASTICITY = 0.0;
    
    private List<Ordinance> ordinances;
    private CollisionEngine collisionEngine;
    
    private WorldDescriptor world;
    
    public OrdinanceManager(WorldDescriptor world)
    {
        this.ordinances = new ArrayList<Ordinance>();
        this.world = world;
        collisionEngine = new CollisionEngine(ELASTICITY);
    }
    
    public synchronized void addOrdinance(Ordinance ordinance)
    {
        ordinances.add(ordinance);
    }
    
    public synchronized void update(double delta, EnemyManager enemyManager)
    {
        List<CollisionPair> willCollide = new CopyOnWriteArrayList<CollisionPair>();
        
        for (Ordinance ordinance: ordinances)
        {
            
            List<Enemy> enemiesForCurOrdinance = new CopyOnWriteArrayList<Enemy>();

            for (Enemy enemy: enemyManager.getEnemies())
            {
                if (collisionEngine.willCollide(ordinance, enemy, delta))
                {
                    enemiesForCurOrdinance.add(enemy);
                }
            }
            
            if(enemiesForCurOrdinance.isEmpty() == false)
            {
                willCollide.add(new CollisionPair(enemiesForCurOrdinance, ordinance));
            }
        }
        
        for (Ordinance ordinance: ordinances)
        {
            ordinance.update(delta);
        }
        
        for (CollisionPair pair: willCollide)
        {
            pair.getOrdinance().affectEnemies(pair.getEnemies());
            ordinances.remove(pair.getOrdinance());
        }
        
        
        
        
        Iterator<Ordinance> ordinanceIterator = ordinances.iterator();
        Ordinance curEntity;
        
        while(ordinanceIterator.hasNext())
        {
            curEntity = ordinanceIterator.next();
            
            if(world.inWorld(curEntity.getLocation()) == false)
            {
                ordinanceIterator.remove();
            }
        }
            
    }
    
    public synchronized Iterable<Ordinance> getOrdinances()
    {
        return Collections.unmodifiableList(ordinances);
    }
    
    private class CollisionPair
    {
        private List<Enemy> enemies;
        private Ordinance ordinance;
        
        private CollisionPair(List<Enemy> enemies, Ordinance ordinance)
        {
            this.enemies = enemies;
            this.ordinance = ordinance;
        }

        public List<Enemy> getEnemies()
        {
            return enemies;
        }

        public Ordinance getOrdinance()
        {
            return ordinance;
        }       
    }
}
